package com.weiwu.weiwustore.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weiwu.weiwustore.entity.*;
import com.weiwu.weiwustore.entity.Record;
import com.weiwu.weiwustore.mapper.*;
import com.weiwu.weiwustore.pojo.*;
import com.weiwu.weiwustore.service.ApplyService;
import com.weiwu.weiwustore.utils.ObjectFormatUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.weiwu.weiwustore.utils.ObjectFormatUtil.toInteger;

@Service
public class ApplyServiceImpl extends ServiceImpl<Apply_recordMapper, Apply_record> implements ApplyService {
    @Autowired
    Apply_recordMapper apply_recordMapper;
    @Autowired
    RecordMapper recordMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    StoreMapper storeMapper;
    @Autowired
    MaterialMapper materialMapper;
    // Spring 框架提供的手动操作事务的两个类
    @Autowired
    private DataSourceTransactionManager transactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

    @Override
    public PageVo<ApplyListVo> getapplysByUser(Map<String, String> map) {
        QueryWrapper<Apply_record> wrapper = new QueryWrapper<>();
        // 根据搜索条件
        Integer size = 10, page = 1;
        String userid = map.get("id");
        IPage pageP = new Page(page, size);
        // 申请单模糊查询
        if (map.containsKey("applyid")) {
            if (map.get("applyid") != "") {
                wrapper.like("applicationid", map.get("applyid"));
            }
        }
        // 状态
        if (map.containsKey("state")) {
            if (map.get("state") != "") {
                wrapper.eq("state", map.get("state"));
            }
        }
        if (map.containsKey("size")) {
            size = toInteger(map.get("size"));
        }
        if (map.containsKey("page")) {
            page = ObjectFormatUtil.toInteger(map.get("page"));
        }
        // 根据用户的id拿申请单
        wrapper.eq("applicantid", userid);
        pageP.setSize(size);
        pageP.setCurrent(page);
        IPage applylist = apply_recordMapper.selectPage(pageP, wrapper);

        PageVo<ApplyListVo> res = new PageVo<>();
        res.setCount(ObjectFormatUtil.toInteger(applylist.getTotal()));
        res.setRes(singlePackApply(applylist.getRecords()));
        return res;
    }

    @Override
    public PageVo<ApplyListVo> getapplysByUserToMG(Map<String, String> map) {
        QueryWrapper<Apply_record> wrapper = new QueryWrapper<>();
        // 根据搜索条件
        Integer size = 10, page = 1;
        String userid = map.get("id");
        IPage pageP = new Page(page, size);
        // 申请单模糊查询
        if (map.containsKey("applyid")) {
            if (map.get("applyid") != "") {
                wrapper.like("applicationid", map.get("applyid"));
            }
        }
        // 状态
        if (map.containsKey("state")) {
            if (map.get("state") != "") {
                wrapper.eq("state", map.get("state"));
            }
        }
        if (map.containsKey("size")) {
            size = toInteger(map.get("size"));
        }
        if (map.containsKey("page")) {
            page = ObjectFormatUtil.toInteger(map.get("page"));
        }
        // 根据用户的id拿用户信息
        User thisuser = userMapper.selectById(ObjectFormatUtil.toInteger(userid));
        if (thisuser == null)
            return new PageVo<ApplyListVo>();
        // 根据出入库类型
        if (map.containsKey("type")) {
            wrapper.eq("type", map.get("type"));
        }
        // 根据用户信息拿到所属仓库信息 拿到所有此仓库下的申请单 如果是系统管理员或仓库主管则拿所有的仓库的申请单
        if (thisuser.getRoleid() != 0 && thisuser.getRoleid() != -1) {
            wrapper.eq("storeid", thisuser.getStoreid());
        }

        pageP.setSize(size);
        pageP.setCurrent(page);
        IPage applylist = apply_recordMapper.selectPage(pageP, wrapper);
        PageVo<ApplyListVo> res = new PageVo<>();
        res.setCount(ObjectFormatUtil.toInteger(applylist.getTotal()));
        res.setRes(singlePackTask(applylist.getRecords()));
        return res;
    }


    @Override
    public PageVo<TaskListVo> gettasksByUser(Map<String, String> map) {
        // 根据搜索条件
        QueryWrapper<Apply_record> wrapper = new QueryWrapper<>();
        Integer size = 10, page = 1;// 如果拿不到分页详情 则默认查第一页且一页10条
        String userid = map.get("id");
        IPage pageP = new Page(page, size);
        // 申请单模糊查询
        if (map.containsKey("applyid")) {
            if (map.get("applyid") != "") {
                wrapper.like("applicationid", map.get("applyid"));
            }
        }
        // 状态
        if (map.containsKey("state")) {
            if (map.get("state") != "") {
                wrapper.eq("state", map.get("state"));
            }
        }
        if (map.containsKey("size")) {
            size = toInteger(map.get("size"));
        }
        if (map.containsKey("page")) {
            page = ObjectFormatUtil.toInteger(map.get("page"));
        }
        pageP.setSize(size);
        pageP.setCurrent(page);
        // 根据用户id查询 申请单的审核人和验收人
        wrapper.and(i -> i.eq("reviewerid", userid).or().eq("checkerid", userid));
        IPage tasklist = apply_recordMapper.selectPage(pageP, wrapper);

        PageVo<TaskListVo> res = new PageVo<>();
        res.setCount(ObjectFormatUtil.toInteger(tasklist.getTotal()));
        res.setRes(singlePackTask(tasklist.getRecords()));
        return res;
    }

    /**
     * 申请单详情
     *
     * @param map 我的申请和我的任务 详情通用
     * @return 申请单详情
     */
    @Override
    public ApplyVo applydetails(Map<String, String> map) {
        return singlePack(apply_recordMapper.selectOne(
                new QueryWrapper<Apply_record>().eq("applicationid", map.get("applicationid"))));
    }

    /**
     * 催单
     *
     * @param map 申请单信息
     * @return
     */
    @Override
    public Integer urge(Map<String, String> map) {
        // 查看当前用户有没有对此单催过 如没有则新增催单信息记录
        // 200是催单成功 400是已经催单过了
        return 200;
    }

    /**
     * 审核或验收
     *
     * @param map 审核提交对象
     * @return
     */
    @Override
    public Integer examine(Map<String, String> map) {
        Integer res = 200;
        String applicationid = map.get("applicationid");
        Integer id = toInteger(map.get("id"));
        String opinion = map.get("opinion");
        String notes = map.get("notes");
        if (userMapper.selectById(id) == null)
            return 400;
        Apply_record apply_record = apply_recordMapper.selectOne(
                new QueryWrapper<Apply_record>().eq("applicationid", applicationid));
        if (apply_record == null)
            return 400;
        return submit(apply_record, id, notes, opinion);
    }

    @Override
    public List<SelectItem> getStateItem() {
        List<SelectItem> res = new ArrayList<>();
        res.add(new SelectItem("0", "待审核"));
        res.add(new SelectItem("1", "审核不通过"));
        res.add(new SelectItem("2", "待验收"));
        res.add(new SelectItem("3", "验收不通过"));
        res.add(new SelectItem("4", "验收完成"));
        return res;
    }

    @Override
    public Integer commitApply(Map<String, Object> map) {
        Integer res = 0;
        Integer userid = toInteger(map.get("userid"));
        Integer storeid = toInteger(map.get("storeid"));
        String type = String.valueOf(map.get("type"));
        List<String> tags = (List<String>) map.get("tags");
        HashMap<String, String> apply = (HashMap<String, String>) map.get("apply");
        List<String> materials = (List<String>) map.get("materials");
        // 添加申请单主体
        Apply_record record = new Apply_record();
        record.setCheckerid(toInteger(apply.get("checker")));
        record.setReviewerid(toInteger(apply.get("reviewer")));
        String applyremark = apply.get("desc");
        if (applyremark.equals("")) {
            record.setApplyremark("无");
        } else {
            record.setApplyremark(applyremark);
        }

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            record.setApplytime(format.parse(apply.get("applyDate")));
        } catch (ParseException e) {
            record.setApplytime(new Date());
            throw new RuntimeException(e);
        }
        record.setState(0);
        record.setStoreid(storeid);
        record.setApplicantid(userid);
        record.setType(type);
        String applicationid = getApplycationid(type);
        record.setApplicationid(applicationid);
        try {
            // 1. 开启事务 (获取事务)
            TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
            apply_recordMapper.insert(record);
            // 添加材料清单
            Record records = null;
            for (int i = 0; i < tags.size(); i++) {
                String tagnum = tags.get(i).substring(0, tags.get(i).indexOf('.'));
                for (int j = 0; j < materials.size(); j++) {
                    records = new Record();
                    String materialsnum = materials.get(j).substring(0, materials.get(j).indexOf('.'));
                    if (tagnum.equals(materialsnum)) {
                        Integer materialid = toInteger(materials.get(j).substring(materials.get(j).indexOf('.') + 1, materials.get(j).indexOf('!')));
                        Integer quantity = toInteger(materials.get(j).substring(materials.get(j).indexOf('!') + 1, materials.get(j).length()));
                        Material mater = materialMapper.selectById(materialid);
                        records.setApplyid(applicationid);
                        records.setState(0);
                        records.setType(type);
                        records.setStoreid(storeid);
                        records.setMname(mater.getMname());
                        records.setQuantity(quantity.doubleValue());
                        records.setPrice((quantity * mater.getPrice()));
                        records.setMaterialid(materialid);
                        res = recordMapper.insert(records);
                    }
                }
            }
            // 2. 自定义提交事务，(或回滚事务)
            transactionManager.commit(transactionStatus);
        } catch (DataAccessException e) {
            // 处理Spring数据访问异常
            System.out.println("捕获数据库访问异常: " + e.getMessage());
            res = 400;
            throw new RuntimeException("事务失败，已回滚", e);
        } catch (Exception e) {
            // 捕获其他所有类型的异常
            System.out.println("捕获异常: " + e.getMessage());
            res = 400;
            throw e; // 重新抛出异常以确保事务能回滚
        }
        return res;
    }

    /**
     * 将申请单转为前端我的申请列表封装类
     *
     * @param apply_records 申请单
     * @return 前端我的申请列表封装类
     */
    private List<ApplyListVo> singlePackApply(List<Apply_record> apply_records) {
        List<ApplyListVo> res = new ArrayList<>();
        if (apply_records.size() == 0)
            return res;
        for (int i = 0; i < apply_records.size(); i++) {
            res.add(i, new ApplyListVo(apply_records.get(i).getApplicationid(),
                    apply_records.get(i).getType(), getStateStr(apply_records.get(i).getState()),
                    userMapper.selectOne(new QueryWrapper<User>().eq("id", apply_records.get(i).getReviewerid())).getUname(),
                    userMapper.selectOne(new QueryWrapper<User>().eq("id", apply_records.get(i).getCheckerid())).getUname(),
                    apply_records.get(i).getApplytime(), apply_records.get(i).getUpdatetime()));
        }
        return res;
    }

    /**
     * 将申请单转为前端我的任务列表封装类
     *
     * @param apply_records 申请单
     * @return 前端我的任务列表封装类
     */
    private List<TaskListVo> singlePackTask(List<Apply_record> apply_records) {
        List<TaskListVo> res = new ArrayList<>();
        if (apply_records.size() == 0)
            return res;
        for (int i = 0; i < apply_records.size(); i++) {
            res.add(i, new TaskListVo(apply_records.get(i).getId(), apply_records.get(i).getApplicationid(),
                    apply_records.get(i).getType(),
                    getStateStr(apply_records.get(i).getState()),
                    userMapper.selectOne(new QueryWrapper<User>().eq("id", apply_records.get(i).getApplicantid())).getUname(),
                    apply_records.get(i).getApplytime(), apply_records.get(i).getApplyremark(),
                    userMapper.selectOne(new QueryWrapper<User>().eq("id", apply_records.get(i).getReviewerid())).getUname(),
                    userMapper.selectOne(new QueryWrapper<User>().eq("id", apply_records.get(i).getCheckerid())).getUname()
            ));
        }
        return res;
    }

    /**
     * 将申请单转为前端申请单封装类
     *
     * @param apply_records 申请单
     * @return 前端申请单封装类
     */
    private ApplyVo singlePack(Apply_record apply_records) {
        ApplyVo applyVo = new ApplyVo(apply_records);
        String applicationid = apply_records.getApplicationid();
        double price = 0;
        List<MaterialVo> materialVos = recordMapper.getMaterialByapplicationid(applicationid);
        for (int i = 0; i < materialVos.size(); i++) {
            price += materialVos.get(i).getPrice();
        }
        // 申请单
        applyVo.setPrice(String.valueOf(price));// 总价值
        applyVo.setState(getStateStr(apply_records.getState()));// 状态
        applyVo.setInstore(storeMapper.selectById(apply_records.getStoreid()).getSname());// 转入仓库
        if ("转移".equals(apply_records.getType())) {
            applyVo.setOutstore(storeMapper.selectById(apply_records.getTransferstoreid()).getSname());// 转出仓库
        }
        applyVo.setApplicantid(getUserNameByid(apply_records.getApplicantid()));// 申请人
        applyVo.setReviewerid(getUserNameByid(apply_records.getReviewerid()));// 审核人
        applyVo.setCheckerid(getUserNameByid(apply_records.getCheckerid()));// 验收人
        // 审核意见和验收意见
        if (apply_records.getReviewpass() != null) {
            applyVo.setReviewpass(apply_records.getReviewpass().equals(1) ? "通过" : "不通过");
        } else {
            applyVo.setReviewpass("");
        }
        if (apply_records.getCheckpass() != null) {
            applyVo.setCheckpass(apply_records.getCheckpass().equals(1) ? "通过" : "不通过");
        } else {
            applyVo.setCheckpass("");
        }
        // 获得申请单的材料清单
        applyVo.setMaterials(materialVos);
        return applyVo;
    }

    private String getStateStr(Integer State) {
        switch (State) {
            case 0:
                return "待审核";
            case 1:
                return "审核不通过";
            case 2:
                return "待验收";
            case 3:
                return "验收不通过";
            case 4:
                return "验收完成";
            default:
                return "暂无";
        }
    }

    private Integer submit(Apply_record apply_record, Integer id, String notes, String opinion) {
        Integer res = 200;
        try {
            // 1. 开启事务 (获取事务)
            TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
            Apply_record record = new Apply_record();
            String noteStr = "";
            if (notes == null || "".equals(notes)) {
                noteStr = "无";
            } else {
                noteStr = notes;
            }
            // 检查申请单的节点是否到当前用户操作

            if (Objects.equals(opinion, "通过")) {
                // 审核
                if (Objects.equals(apply_record.getReviewerid(), id)) {
                    if (apply_record.getReviewpass() == null) {
                        record.setReviewpass(1);
                        record.setReviewremark(noteStr);
                        record.setReviewtime(new Date());
                        record.setState(2);
                    }
                }
                // 验收
                if (Objects.equals(apply_record.getCheckerid(), id)) {
                    if (apply_record.getReviewpass() == null) {
                        return 400;
                    }
                    if (apply_record.getCheckpass() == null) {
                        record.setCheckpass(1);
                        record.setCheckremark(noteStr);
                        record.setChecktime(new Date());
                        record.setState(4);
                        // 同步更新记录表
                        recordMapper.update(new Record(1), new UpdateWrapper<Record>().eq("applyid", apply_record.getApplicationid()));
                    }
                }
            }
            if (Objects.equals(opinion, "不通过")) {
                // 审核
                if (Objects.equals(apply_record.getReviewerid(), id)) {
                    if (apply_record.getReviewpass() == null) {
                        record.setReviewpass(0);
                        record.setReviewremark(noteStr);
                        record.setReviewtime(new Date());
                        record.setState(1);
                    }
                }
                // 验收
                if (Objects.equals(apply_record.getCheckerid(), id)) {
                    if (apply_record.getReviewpass() == null) {
                        return 400;
                    }
                    if (apply_record.getCheckpass() == null) {
                        record.setCheckpass(0);
                        record.setCheckremark(noteStr);
                        record.setChecktime(new Date());
                        record.setState(3);
                    }
                }
            }
            // 修改申请表状态
            apply_recordMapper.update(record, new UpdateWrapper<Apply_record>().eq("applicationid", apply_record.getApplicationid()));
            // 2. 自定义提交事务，(或回滚事务)
            transactionManager.commit(transactionStatus);
        } catch (DataAccessException e) {
            // 处理Spring数据访问异常
            System.out.println("捕获数据库访问异常: " + e.getMessage());
            res = 400;
            throw new RuntimeException("事务失败，已回滚", e);
        } catch (Exception e) {
            // 捕获其他所有类型的异常
            System.out.println("捕获异常: " + e.getMessage());
            res = 400;
            throw e; // 重新抛出异常以确保事务能回滚
        }
        return res;
    }

    private String getUserNameByid(Integer id) {
        User user = userMapper.selectById(id);
        return user == null ? "" : user.getUname();
    }

    private String getApplycationid(String type) {
        StringBuffer res = new StringBuffer();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        String nowDate = format.format(new Date());
        // 日期
        res.append(nowDate);
        // 查询当天的出入库单数量
        QueryWrapper<Apply_record> wrapper = new QueryWrapper<Apply_record>();
        List<Apply_record> stores = new ArrayList<>();
        wrapper.like("applicationid", nowDate).like("applicationid", type.equals("入库") ? "X" : "Y");
        stores = apply_recordMapper.selectList(wrapper);
        Integer applynum = 1;
        if (stores.size() != 0) {
            applynum += stores.size();
        }
        // 补0
        for (int i = 0; i < 5 - applynum.toString().length(); i++) {
            res.append("0");
        }
        res.append(applynum);
        res.append(type.equals("入库") ? "X" : "Y");
        return res.toString();
    }
}
